package ce.com.cenewbluesdk.uitl;



import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * long：时间毫秒数<br>
 * date：Date<br>
 * string：String格式的时间，没指定格式的和string有关的转换，默认用{@link #TEMPLATE_DATETIME}格式<br>
 * ymd：年月日，一月对应着0<br>
 * hms：时分秒<br>
 * dateNoHMS:时分秒为0的Date对象<br>
 * c：Calendar对象<br>
 * DayStart：一天的开始时间（0点）<br>
 * WeekStart：一周的开始时间（周日）<br>
 * MonthStart：一月的开始时间（一号）<br>
 * 以上各者相互转换
 * @author JiangSong
 */
public class TimeUtil {
    public static final long ONE_HOUR_MS = 60 * 60 * 1000;
    public static final long ONE_DAY_MS = 24 * ONE_HOUR_MS;
    public static final long ONE_WEEK_MS = ONE_DAY_MS * 7;

    public static final String TEMPLATE_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String TEMPLATE_DATE = "yyyy-MM-dd";
    public static final String TEMPLATE_TIME = "HH:mm:ss";
    public static final String TEMPLATE_SIMPLE_TIME = "yyyy-MM-dd HH:mm";
    public static final String TEMPLATE_DATETIME_MS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String TEMPLATE_HH_MM = "HH:mm";

    public static String getNowString() {
        return getNowString(TEMPLATE_DATETIME);
    }

    public static String getNowString(String template) {
        return date2String(new Date(now()), template);
    }


    public static long getNowLongDayStart() {
        return long2longDayStart(now());
    }

    public static long getNowLongMonthStart() {
        return long2longMonthStart(now());
    }



    /**
     * 基础方法
     * @param str
     * @param template
     * @return
     */
    public static Date string2Date(String str, String template) {
        SimpleDateFormat format = new SimpleDateFormat(template, Locale.getDefault());
        try {
            return format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date string2Date(String str) {
        return string2Date(str, TEMPLATE_DATETIME);
    }

    public static long string2Long(String str, String template) {
        return string2Date(str, template).getTime();
    }

    public static long string2Long(String str) {
        return string2Date(str).getTime();
    }

    public static int[] string2ymd(String str, String template) {
        return date2ymd(string2Date(str, template));
    }


    public static String date2String(Date date) {
        return date2String(date, TEMPLATE_DATETIME);
    }

    /**
     * 基础方法
     * @param date
     * @param template
     * @return
     */
    public static String date2String(Date date, String template) {
        SimpleDateFormat format = new SimpleDateFormat(template, Locale.getDefault());
        return format.format(date);
    }

    public static int[] date2ymd(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c2ymd(c);
    }

    public static int[] c2ymd(Calendar c) {
        int[] ymd = new int[3];
        ymd[0] = c.get(Calendar.YEAR);
        ymd[1] = c.get(Calendar.MONTH);
        ymd[2] = c.get(Calendar.DAY_OF_MONTH);
        return ymd;
    }

    public static String long2String(long l, String template) {
        return date2String(new Date(l), template);
    }

    public static String long2String(long l) {
        return date2String(new Date(l));
    }

    public static Calendar long2C(long l) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(l);
        return c;
    }

    public static String ymd2String(int year, int month, int day, String template) {
        return date2String(ymd2Date(year, month, day), template);
    }

    public static String ymd2String(int year, int month, int day) {
        return date2String(ymd2Date(year, month, day));
    }

    private static Date c2DateNoHMS(Calendar c) {
        return c2CNoHMS(c).getTime();
    }

    public static Calendar c2CNoHMS(Calendar c) {
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c;
    }

    public static Calendar long2CNoHMS(long time) {
        return c2CNoHMS(long2C(time));
    }



    /**
     * 时间秒数转换成 时：分：秒
     * @param s
     * @return
     */
    public static int[] s2hms(int s) {
        int[] hms = new int[3];
        int m = s / 60;
        hms[2] = s % 60;
        hms[1] = m % 60;
        hms[0] = m / 60;
        return hms;
    }

    /**
     * @param year  同常识
     * @param month 0表示1月
     * @param day   同常识
     * @return
     */
    public static Date ymd2Date(int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.MILLISECOND, 0);
        c.set(year, month, day, 0, 0, 0);
        return c.getTime();
    }

    public static String ms2hhmmss(long l) {
        int i = (int) (l / 1000);
        int h = 0;
        int m = 0;
        int s = 0;
        s = i % 60;
        m = i / 60 % 60;
        h = i / 60 / 60;
        return String.format("%02d:%02d:%02d", h, m, s);
    }

    /**
     * 生日转换成年龄，处理到月
     * @param birthday
     * @return
     */
    public static int birthday2Age(String birthday) {
        int[] oldYmd = string2ymd(birthday, TEMPLATE_DATE);
        int[] nowYmd = c2ymd(Calendar.getInstance());
        return ((nowYmd[0] * 12 + nowYmd[1] + 1) - (oldYmd[0] * 12 + oldYmd[1] + 1)) / 12;
    }

    /**
     * 当前时间减年龄
     * @param age
     * @return
     */
    public static String age2Birthday(int age) {
        Calendar c = Calendar.getInstance();
        int nowY = c.get(Calendar.YEAR);
//        calendar.set(nowY - age, 0, 1, 0, 0, 0);
        c.add(Calendar.YEAR, -age);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return date2String(c.getTime(), TEMPLATE_DATE);
    }

    /**
     * 解析蓝牙传过来的时间
     * @param byteTimeS
     * @param isAbsTime 是否为绝对时间
     * @return
     */
    public static Calendar byte2C(byte[] byteTimeS, boolean isAbsTime) {
        return s2CForDev(ByteUtil.byte4ToInt(byteTimeS), isAbsTime);
    }

    /**
     * @param timeS     时间秒数
     * @param isAbsTime 是否为绝对时间
     * @return
     */
    public static Calendar s2CForDev(int timeS, boolean isAbsTime) {
        long time = timeS * 1000l;
        Calendar c = Calendar.getInstance();
        if (!isAbsTime) {// 若为相对时间
            time = relativeTime2Timestamp(time, c.getTimeZone());
        }
        c.setTimeInMillis(time);
        return c;
    }

    /**
     * 把相对时间/ShowTime转换成时间戳
     * @param value    相对时间/ShowTime
     * @param timeZone 时区
     * @return 时间戳
     */
    public static long relativeTime2Timestamp(long value, TimeZone timeZone) {
        long rawTime = value - timeZone.getRawOffset();// 标准时间
        if (timeZone.useDaylightTime()) {// 使用夏令时
            return value - timeZone.getOffset(rawTime);// 使用标准时间获取offset
        } else {
            return rawTime;
        }
    }

    public static long long2longDayStart(long time) {
        return long2CNoHMS(time).getTimeInMillis();
    }

    public static long long2longWeekStart(long time, int firstDayOfWeek) {
        return long2longWeekStart(time, null, firstDayOfWeek);
    }

    public static long long2longMonthStart(long time) {
        Calendar c = long2CNoHMS(time);
        c.set(Calendar.DAY_OF_MONTH, 1);// 把c设置为本月一号
        return c.getTimeInMillis();
    }

    public static long long2longWeekStart(long time, TimeZone timeZone, int firstDayOfWeek) {
        Calendar c = long2C(time);
        if (timeZone != null) {// 设置时区
            c.setTimeZone(timeZone);
        }
        c2CNoHMS(c);// 去掉hour、min、s、ms
        if (firstDayOfWeek > 0) {// 设置一周开始的天
            c.setFirstDayOfWeek(firstDayOfWeek);
        }
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);// 触发一次计算，防止，接下来设置dayOfWeek出错
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());// 把c设置为一周的第一天
        return c.getTimeInMillis();
    }

    /**
     * long->long，输出一天中从00:00开始，以gap为时间间隔，的某个开始时间
     * @param gap 时间间隔
     */
    public static long long2longGapStart(long time, long gap) {
        long dayStartMs = long2longDayStart(time);
        long count = (time - dayStartMs) / gap;
        return dayStartMs + count * gap;
    }

    public static long now() {
        return System.currentTimeMillis();
    }

    /** GMT时间字符串->long */
    public static long gmt2long(String strGMT) {
        SimpleDateFormat format = new SimpleDateFormat(TEMPLATE_DATETIME);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        Date date = null;
        try {
            date = format.parse(strGMT);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date.getTime();
    }

    /** long->GMT时间字符串 */
    public static String long2gmt(long time) {
        SimpleDateFormat format = new SimpleDateFormat(TEMPLATE_DATETIME);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        return format.format(new Date(time));
    }

    public static Calendar string2C(String str) {
        return string2C(str, TEMPLATE_DATETIME);
    }

    public static Calendar string2C(String str, String template) {
        Calendar c = Calendar.getInstance();
        c.setTime(string2Date(str, template));
        return c;
    }

    public static String c2String(Calendar c) {
        return date2String(c.getTime(), TEMPLATE_DATETIME);
    }

    public static String c2String(Calendar c, String template) {
        return date2String(c.getTime(), template);
    }

    /**
     * 专为处理Dev的时间添加的方法;
     * @param yearSub2K 减去2000之后的year
     * @param monthAdd1 加1之后的month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    @Deprecated
    public static Calendar ymdhms2CForDev(byte yearSub2K, byte monthAdd1, byte day, byte hour, byte minute, byte second) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, yearSub2K + 2000);
        c.set(Calendar.MONTH, monthAdd1 - 1);
        c.set(Calendar.DAY_OF_MONTH, day);
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, second);
        c.set(Calendar.MILLISECOND, 0);
        return c;
    }
}
